import jieba
from device.utils.redis_client import redis_client
from device.services.device_storage import DeviceStorage
from device.utils.stopwords import STOPWORDS


class DeviceQuery:
    """设备模糊查询与分页处理"""
    DEVICE_KEY = 'device:info'

    def __init__(self):
        self.device_ids_set_key = "device:ids"  # 存储所有设备ID的集合
        self.storage = DeviceStorage()

    def _get_device_info(self):
        byte_dict = redis_client.hgetall(self.DEVICE_KEY)
        return {key.decode(): value.decode() for key, value in byte_dict.items()}

    def get_all_devices(self):
        cursor = 0
        pattern = "device:*:info"  # 匹配所有设备哈希键
        while True:
            # 步骤1：用SCAN迭代匹配的设备键
            cursor, device_keys = redis_client.scan(cursor, match=pattern, count=1000)
            all_devices = []
            for item in device_keys:
                str = item.decode()
                parts = str.split(":")
                all_devices.append(parts[1])
            if cursor == 0:
                break  # 迭代结束
        return all_devices

    def _get_matched_ids(self, keyword, fields=None):
        """根据关键词和字段获取匹配的设备ID"""
        # 1. 处理查询字段（默认查所有支持的字段）
        query_fields = fields or self.storage.SUPPORTED_FIELDS
        query_fields = [f for f in query_fields if f in self.storage.SUPPORTED_FIELDS]
        # 2. 无关键词时返回所有设备（从索引反推，或维护一个全量ID集合）
        if not keyword.strip():
            # 这里简化处理：从第一个字段的所有索引中取并集（实际可维护一个device:all_ids集合）
            all_index_keys = [self.storage._get_index_key(f, "*") for f in query_fields]
            return {id.decode() for id in redis_client.sunion(*all_index_keys)} if all_index_keys else set()

        # 3. 关键词分词并过滤
        words = jieba.lcut(keyword.strip().lower())
        valid_words = [w for w in words if w.strip() and w not in STOPWORDS]
        if not valid_words:
            return set()

        # 4. 收集所有字段+词的索引键，取并集（任意字段包含关键词即匹配）
        index_keys = [self.storage._get_index_key(f, w) for f in query_fields for w in valid_words]
        matched_ids = redis_client.sunion(*index_keys)  # 并集：满足任一条件
        return {id.decode() for id in matched_ids}

    def paginate(self, matched_ids, page=1, page_size=20):
        """对匹配的设备ID分页"""
        total = len(matched_ids)
        if total == 0:
            print("分页：无匹配数据，返回空")
            return [], 0, 0

        # 分页参数处理（增加类型校验和日志）
        try:
            page = int(page)
            page_size = int(page_size)
        except (ValueError, TypeError):
            print(f"分页：参数错误，page={page}, page_size={page_size}，使用默认值")
            page = 1
            page_size = 20

        page = max(page, 1)
        page_size = min(page_size, 100)  # 限制最大页大小
        total_pages = (total + page_size - 1) // page_size
        start = (page - 1) * page_size
        end = start + page_size

        # 排序后切片
        sorted_ids = sorted(matched_ids)
        page_ids = sorted_ids[start:end]

        # 打印调试信息
        print(f"分页调试：total={total}, page={page}, page_size={page_size}")
        print(f"分页调试：start={start}, end={end}, 本页数量={len(page_ids)}, 总页数={total_pages}")

        return page_ids, total, total_pages

    # def paginate(self, matched_ids, page=1, page_size=20):
    #     """对匹配的设备ID分页"""
    #     total = len(matched_ids)
    #     if total == 0:
    #         return [], 0, 0
    #
    #     # 分页参数处理
    #     page = max(int(page), 1)
    #     page_size = min(int(page_size), 100)
    #     total_pages = (total + page_size - 1) // page_size
    #     start = (page - 1) * page_size
    #     end = start + page_size
    #
    #     # 排序后切片（保证分页顺序稳定）
    #     sorted_ids = sorted(matched_ids)
    #     return sorted_ids[start:end], total, total_pages

    def search(self, keyword="", fields=None, page=1, page_size=20):
        """执行查询并返回分页结果"""
        # 1. 获取匹配的设备ID
        try:
            if not keyword.strip():
                matched_ids = self.get_all_devices()
            else:
                matched_ids = self._get_matched_ids(keyword, fields)
            # 2. 分页
            page_ids, total, total_pages = self.paginate(matched_ids, page, page_size)
            # 3. 获取设备详情
            devices = [self.storage.get_device(id) for id in page_ids if self.storage.get_device(id)]
            return {
                "data": devices,
                "pagination": {
                    "total": total,
                    "page": page,
                    "page_size": page_size,
                    "total_pages": total_pages
                }
            }
        except Exception as e:
            print(f"错误：{e}")
            return  {
                "data": [],
                "pagination": {
                    "total": total,
                    "page": page,
                    "page_size": page_size,
                    "total_pages": total_pages
                }
            }